001 package EVolve;
002
003 import EVolve.*;
004 import EVolve.exceptions.*;
005 import EVolve.data.*;
006 import EVolve.util.*;
007
008 import java.io.*;
009 import java.util.*;
010 import javax.swing.*;
011
012 import adaptj.*;
013 import adaptj.util.*;
014 import adaptj.toolkits.*;
015 import adaptj.toolkits.continuous.*;
016
017 import it.unimi.dsi.fastUtil.*;
018
019 public class ContinuousDataSource implements DataSource {
020 public static final String DATASOURCE_NAME = "ContinuousDataSource";
021
022 private BufferedFileReader input;
023 private long mark = 0L;
024 private String currentFileName;
025
026 private Int2ObjectOpenHashMap metrics;
027 private Int2ObjectOpenHashMap triggers;
028 //private Int2ObjectOpenHashMap metricToTriggers;
029
030 private int maxMetricID;
031 private int maxTriggerID;
032
033 // For iterating over all definitions
034 private int currentMetricID;
035 private int currentTriggerID;
036
037 // double arrays are indexed by metric ID, then trigger ID
038 private long[] eventCounts;
039 private ElementDefinition[] definitions;
040 private List[] fields;
041 private EventBuilder[] builders;
042
043 private EntityBuilder triggerEntityBuilder;
044 private Int2ObjectOpenHashMap triggerEntities;
045
046 private LineTokenizer tokenizer;
047
048 private String[] propertyCount = {"time", "count"};
049 private String[] propertyAmount = {"time", "amount"};
050 private String[] propertyMetric = {"metric"};
051 private String[] propertyTrigger = {"trigger"};
052
053 public void init() throws EVolveException {
054 String fn = EVolve.Scene.getDataFileName();
055 if (fn == null) {
056 JFileChooser fc = new JFileChooser(EVolve.Scene.getUIManager().getLastDataDir());
057 if (fc.showOpenDialog(EVolve.Scene.getFrame()) == JFileChooser.APPROVE_OPTION) {
058 try {
059 File f = fc.getSelectedFile();
060 input = new BufferedFileReader(f);
061 fn = f.getName();
062 EVolve.Scene.setDataFilename(f.getPath());
063 EVolve.Scene.getUIManager().setLastDataDir(f.getPath());
064 EVolve.Scene.setDataFilename(null);
065 } catch (IOException e) {
066 throw new DataProcessingException("IO exception occurred when access data file.");
067 }
068 } else {
069 throw new CancelLoadDataException();
070 }
071 } else {
072 try {
073 input = new BufferedFileReader(fn);
074 } catch (IOException e) {
075 throw new DataProcessingException("File loading failed.");
076 }
077 }
078
079 currentFileName = fn;
080 tokenizer = new LineTokenizer();
081 }
082
083 public String getName() {
084 return DATASOURCE_NAME;
085 }
086
087 public String getFileName() {
088 return currentFileName;
089 }
090
091 public void startBuildDefinition() throws DataProcessingException {
092 String line;
093 maxMetricID = 0;
094 maxTriggerID = 0;
095
096 metrics = new Int2ObjectOpenHashMap();
097 triggers = new Int2ObjectOpenHashMap();
098 //metricToTriggers = new Int2ObjectOpenHashMap();
099
100 // Reminder: file format
101 // TRIGGER <id> <trigger description> [INTERVAL]
102 // METRIC <id> <name>
103 // MAP <trigger id> <metric id>+
104 // <trigger id> <metric id> <metric value> [interval counter]
105 try {
106 while ((line = input.readLine()) != null) {
107 line = line.trim();
108 if (line.startsWith("#")) {
109 // This input line is a comment -- Skip it
110 } else if (line.equals("")) {
111 // This input line is a blank line -- Skip it
112 } else if (line.startsWith("TRIGGER")) {
113 tokenizer.setLine(line);
114 // Skip "TRIGGER"
115 tokenizer.getNext();
116
117 int triggerIndex = Integer.parseInt(tokenizer.getNext());
118 String triggerDesc = tokenizer.getRemaining();
119 boolean interval = false;
120 if (triggerDesc.endsWith(" INTERVAL")) {
121 interval = true;
122 triggerDesc = triggerDesc.substring(0, triggerDesc.length() - 9);
123 }
124 triggers.put(triggerIndex, triggerDesc);
125 if (maxTriggerID < triggerIndex) {
126 maxTriggerID = triggerIndex;
127 }
128
129 // DEBUG
130 System.out.println("Trigger: " + triggerIndex + " " + triggerDesc + (interval ? " [INTERVAL]" : ""));
131 } else if (line.startsWith("METRIC")) {
132 tokenizer.setLine(line);
133 // Skip "METRIC"
134 tokenizer.getNext();
135
136 int metricIndex = Integer.parseInt(tokenizer.getNext());
137 String metricName = tokenizer.getRemaining();
138 metrics.put(metricIndex, metricName);
139 if (maxMetricID < metricIndex) {
140 maxMetricID = metricIndex;
141 }
142
143 // DEBUG
144 System.out.println("Metric: " + metricIndex + " " + metricName);
145 } else if (line.startsWith("MAP")) {
146 // Ignore at this time
147 /*
148 tokenizer.setLine(line);
149
150 // Skip "MAP"
151 tokenizer.getNext();
152
153 int triggerIndex = Integer.parseInt(tokenizer.getNext());
154 while (tokenizer.hasNext()) {
155 int metricIndex = Integer.parseInt(tokenizer.getNext());
156 IntHashSet triggerSet;
157 if (metricToTriggers.containsKey(metricIndex)) {
158 triggerSet = (IntHashSet) metricToTriggers.get(metricIndex);
159 } else {
160 triggerSet = new IntHashSet("ContinuousDataSource.Metric#" + metricIndex);
161 metricToTriggers.put(metricIndex, triggerSet);
162 }
163 triggerSet.add(triggerIndex);
164 }
165 */
166 // DEBUG
167 //System.out.println("Map");
168 } else {
169 System.out.println("Starting to read events");
170 break;
171 }
172 mark = input.getFilePointer();
173 }
174
175 eventCounts = new long[maxMetricID + 1];//[maxTriggerID + 1];
176 definitions = new ElementDefinition[maxMetricID + 1];//[maxTriggerID + 1];
177 fields = new List[maxMetricID + 1];//[maxTriggerID + 1];
178 builders = new EventBuilder[maxMetricID + 1];//[maxTriggerID + 1];
179
180 while (line != null) {
181 tokenizer.setLine(line);
182 // Trigger index
183 //int triggerIndex = Integer.parseInt(tokenizer.getNext());
184
185 // Metric index
186 int metricIndex = Integer.parseInt(tokenizer.getNext());
187
188 //eventCounts[metricIndex][triggerIndex] += 1L;
189 eventCounts[metricIndex] += 1L;
190 line = input.readLine();
191 }
192 } catch (IOException e) {
193 throw new DataProcessingException("File processing failed.");
194 //} catch (ArrayIndexOutOfBoundsException e) {
195 // throw new DataProcessingException("File processing failed (invalid file format).");
196 }
197
198 currentMetricID = 0;
199 //currentTriggerID = 0;
200 System.out.println("Definitions built. Will iterate next");
201 System.out.println("Max Metric ID = " + maxMetricID);
202 System.out.println("Max Trigger ID = " + maxTriggerID);
203 }
204
205 public ElementDefinition getNextDefinition() throws DataProcessingException {
206 ElementDefinition result = null;
207
208 if (triggerEntityBuilder == null) {
209 triggerEntityBuilder = new EntityBuilder("Trigger", "Trigger");
210 return triggerEntityBuilder.buildDefinition();
211 }
212
213 for (int i = currentMetricID; i <= maxMetricID && result == null; i++, currentMetricID++) {
214 if (eventCounts[i] > 0L) {
215 // Build an event definition for this
216 String eventName = (String) metrics.get(i); // + " - " + triggers.get(j);
217 EventBuilder builder = new EventBuilder(eventName, eventName);
218 List l = new ArrayList();
219 l.add(builder.buildReferenceDefinition("Trigger", triggerEntityBuilder, propertyTrigger, "Trigger"));
220 l.add(builder.buildValueDefinition("Occurences", propertyCount, "Occurences"));
221 l.add(builder.buildValueDefinition("Value", propertyMetric, "Metric Value"));
222 result = builder.buildDefinition();
223
224 fields[i] = l;
225 definitions[i] = result;
226 builders[i] = builder;
227 }
228 }
229
230 /*
231 for (int i = currentMetricID; i <= maxMetricID; i++, currentMetricID++) {
232 for (int j = currentTriggerID; j <= maxTriggerID; j++, currentTriggerID++) {
233 if (eventCounts[i][j] > 0L) {
234 // Build an event definition for this
235 String eventName = (String) metrics.get(i); // + " - " + triggers.get(j);
236 EventBuilder builder = new EventBuilder(eventName, eventName);
237 List l = new ArrayList();
238 l.add(builder.buildValueDefinition("Value", propertyMetric, "Metric Value"));
239 l.add(builder.buildValueDefinition("Occurences", propertyCount, "Occurences"));
240 l.add(builder.buildReferenceDefinition("Trigger", triggerEntityBuilder, propertyTrigger, "Trigger"));
241 result = builder.buildDefinition();
242
243 fields[i][j] = l;
244 definitions[i][j] = result;
245 builders[i][j] = builder;
246
247 System.out.println("Looked at (" + i + ", " + j + ") --> " + eventName);
248
249 if (result != null) {
250 if (++currentTriggerID > maxTriggerID) {
251 currentTriggerID = 0;
252 currentMetricID++;
253 }
254
255 return result;
256 }
257 }
258 }
259 }
260 */
261
262
263
264 return result;
265 }
266
267 public long getNumberOfEvents(String definitionName) {
268 for (int i = 0; i < maxMetricID; i++) {
269 ElementDefinition def = definitions[i];
270 if (def != null && definitionName.equals(def.getName())) {
271 return eventCounts[i];
272 }
273 }
274 return 0L;
275 }
276
277 public long getTotalNumberOfEvents() {
278 long result = 0L;
279 for (int i = 0; i < maxMetricID; i++) {
280 result += eventCounts[i];
281 }
282
283 return result;
284 }
285
286 public void startBuildEntity() throws DataProcessingException {
287 currentTriggerID = 0;
288 triggerEntities = new Int2ObjectOpenHashMap();
289 }
290
291 public Entity getNextEntity() throws DataProcessingException {
292 if (currentTriggerID <= maxTriggerID) {
293 triggerEntityBuilder.newEntity((String) triggers.get(currentTriggerID));
294 Entity triggerEntity = triggerEntityBuilder.buildEntity();
295 triggerEntities.put(currentTriggerID, triggerEntity);
296 currentTriggerID++;
297 return triggerEntity;
298 }
299
300 return null;
301 }
302
303 public void startBuildEvent() throws DataProcessingException {
304 try {
305 input.seek(mark);
306 } catch (IOException e) {
307 throw new DataProcessingException("File processing failed");
308 }
309 }
310
311 public Event getNextEvent() throws DataProcessingException {
312 Event result = null;
313 try {
314 String line;
315 while ((line = input.readLine()) != null) {
316 int currentField = 0;
317 tokenizer.setLine(line);
318 // Trigger index
319 int triggerIndex = Integer.parseInt(tokenizer.getNext());
320 // Metric index
321 int metricIndex = Integer.parseInt(tokenizer.getNext());
322 // Metric value
323 double metric = Double.parseDouble(tokenizer.getNext());
324
325 System.err.println("Trigger: " + triggerIndex + " Metric: " + metricIndex + " Value: " + metric);
326
327 // Interval counter
328 /*
329 int intervalCounter = -1;
330 if (tokenizer.hasNext()) {
331 intervalCounter = Integer.parseInt(tokenizer.getNext());
332 }
333 */
334
335 EventBuilder builder = builders[metricIndex];
336 List l = fields[metricIndex];
337
338 builder.newEvent();
339 builder.addValueField((FieldDefinition)l.get(currentField++), (int)(metric * 1000));
340 builder.addValueField((FieldDefinition)l.get(currentField++), 1);
341 builder.addReferenceField((FieldDefinition)l.get(currentField++), (Entity)triggerEntities.get(triggerIndex));
342
343 return builder.buildEvent();
344 }
345 } catch (IOException e) {
346 throw new DataProcessingException("File processing failed");
347 }
348
349 return null;
350 }
351
352
353 class LineTokenizer {
354 private String line;
355 private int start;
356 private int end;
357 private int len;
358
359 LineTokenizer() {
360 this(null);
361 }
362
363 LineTokenizer(String line) {
364 setLine(line);
365 }
366
367 public void setLine(String line) {
368 this.line = line;
369 if (line != null) {
370 line = line.trim();
371 len = line.length();
372 } else {
373 len = -1;
374 }
375 start = 0;
376 end = 0;
377 }
378
379 public boolean hasNext() {
380 return end < len;
381 }
382
383 public String getNext() {
384 if (end < len) {
385 end = line.indexOf(' ', start);
386 if (end < 0) {
387 end = len;
388 }
389
390 String result = line.substring(start, end);
391 start = end + 1;
392 return result;
393 }
394
395 return null;
396 }
397
398 public String getRemaining() {
399 if (end < len) {
400 end = len;
401 return line.substring(start);
402 }
403
404 return null;
405 }
406 }
407 }
408